
//

/**
 * 模仿原生call函数
 * 使用call之前需要思考是否要改变其函数里的this指向
 * @param {*} fn 回调函数
 * @param {*} thisArg this指向
 * @param  {...any} args 参数
 * @returns 
 */
 function call(fn,thisArg,...args){
    if(typeof fn === 'function'){
        if(typeof thisArg != 'object' || thisArg === null){
            thisArg=window;
        }
        thisArg.tmpFn=fn;
        const res=thisArg.tmpFn(...args);
        delete thisArg.tmpFn
        return  res;
    }
    return undefined;
   
}

/**
 * 模仿原生apply函数
 * 和call 一样，就是args的参数是数组
 * @param {*} fn 回调函数
 * @param {*} thisArg this指向
 * @param  {Array} args 参数
 * @returns 
 */
function apply(fn,thisArg,args){
    call(fn,thisArg,...args)
}

/**
 * 模仿原生bind函数
 * 使用call之前需要思考是否要改变其函数里的this指向
 * 场景：
 * 1.当你想改变函数指向然后又暂时不想执行函数时
 * 2.当你想给函数预设参数时
 * @param {*} fn 回调函数
 * @param {*} thisArg this指向
 * @param  {...any} args 参数 会占用 args2的参数
 * @returns 
 */
function bind(fn,thisArg,...args){
    return function(...args2){
        return fn.call(thisArg,...args,...args2)
    }
}

function throttle(callback,wait){
    /**
     * - 理解: 
        - 在函数需要频繁触发时: 函数执行一次后，只有大于设定的执行周期后才会执行第二次
        - 适合多次事件按时间做平均分配触发
    - 场景：    
        - 窗口调整（resize）
        - 页面滚动（scroll）
        - DOM 元素的拖拽功能实现（mousemove）
        - 抢购疯狂点击（click）
    解决方案 设置一个启动时间，当每次执行的时候把当前时间作比较，小于限定时间则不操作，大于限定时间则执行
     */
    let start=0;
    return function(e){
        const now=Date.now();
        if(now-start>wait){
            callback.call(this,e)
            start=now;
        }
    }
}

